package crypto

import (
	"bytes"
	"crypto/rand"
	"strings"

	"github.com/adwindone/sdk-go/util/types"

	"github.com/tjfoc/gmsm/sm2"
	"github.com/tjfoc/gmsm/sm3"
	"github.com/tjfoc/gmsm/x509"
)

const (
	IDA = "1234567812345678"
)

// Sm3Hash computes the SM3 hash of the given message.
func Sm3Hash(msg []byte) []byte {
	h := sm3.New()
	_, _ = h.Write(msg)
	return h.Sum(nil)
}

// Signature generates a signature for the given transaction hash using the provided private key.
func Signature(privateKey string, txHash []byte) ([]byte, error) {
	priv, err := x509.ReadPrivateKeyFromHex(strings.TrimPrefix(privateKey, "0x"))
	if err != nil {
		return nil, err
	}

	r, s, err := sm2.Sm2Sign(priv, txHash, []byte(IDA), rand.Reader)
	if err != nil {
		return nil, err
	}

	sb := bytes.Buffer{}
	byteR := types.LeftPadBytes(r.Bytes(), 32)
	_, err = sb.Write(byteR)
	if err != nil {
		return nil, err
	}

	byteS := types.LeftPadBytes(s.Bytes(), 32)
	_, err = sb.Write(byteS)
	if err != nil {
		return nil, err
	}

	bytePublicKeyX := types.LeftPadBytes(priv.PublicKey.X.Bytes(), 32)
	_, err = sb.Write(bytePublicKeyX)
	if err != nil {
		return nil, err
	}

	bytePublicKeyY := types.LeftPadBytes(priv.PublicKey.Y.Bytes(), 32)
	_, err = sb.Write(bytePublicKeyY)
	if err != nil {
		return nil, err
	}
	return sb.Bytes(), nil
}
